#include "registermodule.h"
#include "registerLoginMessage.pb.h"
#include "utils/TimeOperation.h"
#include "utils/config.h"
#include "utils/keymanager.h"
#include <openssl/rand.h>
using namespace videoMettingServer;

registerModule::registerModule() {}

/**
 * @brief registerLoginModule::initialize  这个初始化主要用来设置好客户端的公钥证书并且计算和服务器通信的密钥的
 * @return 
 */
bool registerModule::initialize()
{
    //首先需要加载到公钥证书，CA的公钥的已将加载了的，这里只需要加载自己的就行了，这里也
    clientCert_PEM = certManger.readPemFile(CLIENT_CERT_FILEPATH);
    if (clientCert_PEM.empty()) {
        OPERATION_FAIL("clientCert_PEM is empty", "registerModule", __FILE__, __LINE__, "");
        return false;
    }

    //计算会话密钥的前提是，看看别的模块是否已经计算好了，如果没有才计算
    if (!keyManager::instance().getSymmKeyIsSeted()) {
        sessionKey_vector = computeSessionKey(keyManager::instance().getPriKey().get(),
                                              keyManager::instance().getCAPubKey().get(),
                                              keyManager::instance().getSalt().get());
        if (sessionKey_vector.empty()) {
            OPERATION_FAIL("sessionKey_vector is empty",
                           "registerLoginModule",
                           __FILE__,
                           __LINE__,
                           "");
            return false;
        }
        keyManager::instance().setSymmKey(sessionKey_vector);
    } else {
        sessionKey_vector = keyManager::instance().getSymmKey();
    }

    return true;
}

QByteArray registerModule::execute()
{
    //这里面执行的就是，将手机号和密码写进去封装成消息
    std::string requestMessage = constructRegistrationRequestMessage();
    if (requestMessage.empty()) {
        OPERATION_FAIL("requestMessage is empty", "registerLoginModule", __FILE__, __LINE__, "");
        return {};
    }
    //然后就是加密了并构造安全消息啦
    std::string safeMessage = constructSafeRegistrationRequestMessage(requestMessage);
    if (safeMessage.empty()) {
        OPERATION_FAIL("safeMessage is empty", "registerLoginModule", __FILE__, __LINE__, "");
        return {};
    }

    return QByteArray(safeMessage.c_str(), safeMessage.size());
}

bool registerModule::handleReceiveData(const QByteArray &receiveData)
{
    //这个只包含请求成功没，因此不需要加密的但是是有hmac的
    std::string data = receiveData.toStdString();
    // std::cout << "data size: " << data.size() << std::endl;
    //需要反序列消息
    SafeMessage safemessage;
    if (!safemessage.ParseFromString(data)) {
        OPERATION_FAIL("safemessage.ParseFromString", "registerLoginModule", __FILE__, __LINE__, "");
        return false;
    }

    //获取到响应消息的数据
    std::string responseData = safemessage.encrypted_data(); //密文
    std::string sessionKey_str(sessionKey_vector.begin(), sessionKey_vector.end());

    //需要解密，需要获得iv
    //unsigned char plainText[responseData.size()] = {0};
    std::vector<unsigned char> plainText(responseData.size(), 0);
    int plainTextLen = 0;
    bool ret = m_symm.aes_Decryption(sessionKey_vector.data(),
                                     reinterpret_cast<const unsigned char *>(
                                         safemessage.iv().c_str()),
                                     reinterpret_cast<const unsigned char *>(responseData.c_str()),
                                     static_cast<int>(responseData.size()),
                                     plainText.data(),
                                     &plainTextLen);
    if (!ret) {
        OPERATION_FAIL("Failed to aes_Decryption", "registerLoginModule", __FILE__, __LINE__, "");
        return false;
    }

    //计算hmac
    std::vector<unsigned char> hmac1 = m_ecc.calculateHMAC(sessionKey_str, responseData);
    std::string hmac1_str(hmac1.begin(), hmac1.end());

    std::string hmac2_str = safemessage.hmac();
    if (!m_ecc.verifyHmac(hmac1_str, hmac2_str)) {
        OPERATION_FAIL("verifyHmac", "registerModule", __FILE__, __LINE__, "");
        return false;
    }

    //反序列化响应消息
    std::string responseMessage_str(reinterpret_cast<const char *>(plainText.data()), plainTextLen);
    RegistrationResponseMessage responsemessage;
    if (!responsemessage.ParseFromString(responseMessage_str)) {
        OPERATION_FAIL("responsemessage.ParseFromString",
                       "registerLoginModule",
                       __FILE__,
                       __LINE__,
                       "");
        return false;
    }

    //然后就是获得标志
    ResponseStatus status = responsemessage.status();
    std::string response_data = responsemessage.response_data();
    response_result = response_data; //赋值给response_result 以便上层获取
    return true;
}

void registerModule::setPhoneNumberPasswd(const QString &phoneNumber, const QString &passwd)
{
    m_phoneNumber = phoneNumber;
    m_passwd = passwd;
}

QString registerModule::getResponseResult()
{
    return QString::fromStdString(response_result);
}

std::vector<unsigned char> registerModule::computeSessionKey(BIGNUM *clientPriKey,
                                                             EC_POINT *peerPubKey,
                                                             unsigned char *salt)
{
    if (!salt) {
        OPERATION_FAIL("Salt is nullptr", "OVDataProcess", __FILE__, __LINE__, "");
        return {};
    }

    //对端公钥已经获取了
    // 对端公钥需要有效
    if (!peerPubKey) {
        OPERATION_FAIL("Peer public key is nullptr", "OVDataProcess", __FILE__, __LINE__, "");
        return {};
    }
    unsigned char out_key[32] = {0};
    //计算会话密钥
    if (!m_ecc.deriveSymmetricKey(m_ecc.getGroup(), peerPubKey, clientPriKey, salt, out_key)) {
        OPERATION_FAIL("deriveSymmetricKey", "OVDataProcess", __FILE__, __LINE__, "");
    }

    std::vector<unsigned char> session_key_vector(out_key, out_key + 32);
    std::fill(std::begin(out_key), std::end(out_key), 0); // 清理敏感数据
    // OPERATION_SUCCESS("Session key derived successfully", "OVDataProcess", "");
    return session_key_vector;
}

std::string registerModule::constructRegistrationRequestMessage()
{
    RegistrationRequestMessage requestMessage;
    requestMessage.set_phone_number(m_phoneNumber.toStdString());
    requestMessage.set_passwd(m_passwd.toStdString());

    //然后就是序列化为字符串
    std::string requestMessage_str;
    if (!requestMessage.SerializePartialToString(&requestMessage_str)) {
        OPERATION_FAIL("requestMessage SerializePartialToString",
                       "registerLoginModule",
                       __FILE__,
                       __LINE__,
                       "");
        return "";
    }

    return requestMessage_str;
}

std::string registerModule::constructSafeRegistrationRequestMessage(const std::string &data)
{
    //生成IV

    unsigned char iv[16] = {0};
    RAND_bytes(iv, 16);

    std::string iv_str(reinterpret_cast<const char *>(iv), 16);
    //加密数据的长度，需要先预估长度
    int maxCipherTextLen = static_cast<int>(data.size()) + EVP_CIPHER_block_size(EVP_aes_256_cbc());
    auto cipherText = (unsigned char *) OPENSSL_malloc(maxCipherTextLen);
    int cipherTextLen = 0;
    int encryptResult = m_symm.aes_Encryption(sessionKey_vector.data(),
                                              iv,
                                              reinterpret_cast<const unsigned char *>(data.c_str()),
                                              static_cast<int>(data.size()),
                                              cipherText,
                                              &cipherTextLen);
    if (!encryptResult) {
        OPERATION_FAIL(" aes_Encryption ", "OVDataProcess", __FILE__, __LINE__, "");
        return "";
    }

    std::string cipherText_str(reinterpret_cast<const char *>(cipherText), cipherTextLen);

    OPENSSL_free(cipherText);

    std::string salt_str(reinterpret_cast<const char *>(keyManager::instance().getSalt().get()), 16);

    std::string sessionKey_str(sessionKey_vector.begin(), sessionKey_vector.end());

    //计算hmac
    std::vector<unsigned char> hmac = m_ecc.calculateHMAC(sessionKey_str, cipherText_str);
    std::string hmac_str(hmac.begin(), hmac.end());

    //封装消息
    SafeMessage safe_message;
    safe_message.set_message_type(MessageType::REGISTRATIONREQUEST);
    safe_message.set_pubkey_cert(clientCert_PEM);
    safe_message.set_encrypted_data(cipherText_str);
    safe_message.set_iv(iv_str);
    safe_message.set_salt(salt_str);
    safe_message.set_hmac(hmac_str);

    //序列化成字符串
    std::string safe_message_str;
    if (!safe_message.SerializePartialToString(&safe_message_str)) {
        OPERATION_FAIL(" encrypted_registration_message.SerializeToString ",
                       "OVDataProcess",
                       __FILE__,
                       __LINE__,
                       "");
        return "";
    }

    return safe_message_str;
}
